home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 10 / FM Towns Free Software Collection 10.iso / ms_dos / lib / happysrc / pimain.c < prev    next >
Text File  |  1994-11-13  |  16KB  |  427 lines

  1. /************************************************
  2.  **
  3.  **    *** HAPPy P-code Interpreter ***
  4.  **
  5.  **             メイン処理
  6.  **
  7.  **          Copyright (c) H.Asano. 1992-1994.
  8.  ************************************************/
  9.  
  10. #define EXTERN
  11.  
  12. #include <signal.h>
  13. #include <process.h>
  14. #include <io.h>
  15. #include <conio.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <ctype.h>
  20. #include <float.h>
  21. #include "version.h"
  22. #include "hapai.h"
  23.  
  24. #define abnormal  1                     /* usage関数への引数          */
  25. #define normal    0                     /* usage関数への引数          */
  26.  
  27. extern void interpret(void) ;   /* P-code命令解釈実行処理             */
  28.  
  29. _store  store[Maxstore] ;       /* 記憶装置                           */
  30.  
  31. _store *sp   ;                  /* stack pointer                      */
  32. short   pc   ;                  /* program counter                    */
  33. short   mp   ;                  /* begginning of a data segment       */
  34. short   ep   ;                  /* the maxmum extent of the stack     */
  35. short   np   ;                  /* top of the dynamically allocated area */
  36.  
  37. _code   cd   ;                  /* P-code                             */
  38.  
  39. short   fileno   ;              /* ファイル数                         */
  40.  
  41. boolean trace             ;     /* 命令トレースフラグ                 */
  42. boolean readlnflag = true ;     /* 起動時及びinputにreadlnをした時 真 */
  43.  
  44. const  char *ext = ".pco" ;     /* P-codeオプジェクトファイルの拡張子 */
  45. static char pcofname[50]  ;     /* P-codeオブジェクトファイル名       */
  46. static char progname[33]  ;     /* Pascalプログラム名                 */
  47.  
  48. static short   objsize  ;
  49. static FILE    *pcofile ;
  50. static boolean infor = false ;          /* -iオプション  インタプリタ情報出力  */
  51. static boolean fileoptflag = false ;    /* /fオプション  ファイル名指定       */
  52. static short   fno      ;               /* /fオプションで取得したファイル数   */
  53. static int     wargc    ;               /* argc 退避                  */
  54. static char    **wargv  ;               /* argv 退避                  */
  55.  
  56. /******************************************/
  57. /*  puteoln() : 終了時のeoln付与処理      */
  58. /******************************************/
  59. void puteoln(void)
  60. {
  61.    short i ;
  62.  
  63.      for(i=0;i<fileno;i++) {            /* ファイルクローズを行う     */
  64.       if((fi[i].mode == generation) &&  /* 生成モードでテキストで     */
  65.          (fi[i].textfile) && (!fi[i].writelnflag)) /* 最後が改行でない*/
  66.         fputc('\n',fi[i].fp) ;          /* 改行を付け加える           */
  67.       fclose(fi[i].fp) ;                /* エラーチェックはしない     */
  68.      }
  69. }
  70.  
  71. /******************************/
  72. /* title() : タイトル表示処理 */
  73. /******************************/
  74. static void title(void)
  75. {
  76.   static putflag = false ;
  77.  
  78.   if(!putflag) {                        /* 一度だけ表示する           */
  79.    fprintf(stderr,
  80.     "HAPPy P-code Interpreter Version %s  Copyright (c) H.Asano 1992-1994.\n",
  81.                                     version) ;
  82.    putflag = true ;
  83.   }
  84. }
  85.  
  86. /******************************************/
  87. /* prerr() : Run-timeエラーメッセージ出力 */
  88. /******************************************/
  89. void prerr(short errno,char *msg)
  90. {
  91.      fprintf(stderr,"\n*** [ADDR=%d] HAPPy Run-time error R%03d:\n   --  %s",
  92.                     pc-1,errno,msg) ;
  93.      fputs(" : 処理打ち切り ***\n",stderr);
  94.      puteoln() ;                        /* ファイルクローズ & eoln付与*/
  95.      exit(1)   ;                        /* ランタイムエラーで終了     */
  96. }
  97.  
  98. /**********************************************/
  99. /* pierr() : インタプリタエラーメッセージ出力 */
  100. /**********************************************/
  101. static void pierr(char *msg, char *umecomi)
  102. {
  103.      title() ;
  104.      fprintf(stderr,msg,umecomi) ;
  105.      exit(2) ;                          /* その他のエラーで終了       */
  106. }
  107.  
  108. /****************************************/
  109. /*   cntl_c(): cntl_cが押された時の処理 */
  110. /****************************************/
  111. static void cntl_c(int sig, int subcode)
  112. {
  113.      prerr(152,"<CTRL-C>を受け付けた");
  114. }
  115.  
  116. /****************************************/
  117. /*   real_err(): 浮動小数点例外         */
  118. /****************************************/
  119. static void real_err(int sig, int subcode)
  120. {
  121.   char *type ;
  122.   char buf[80] ;
  123.  
  124.      switch(subcode) {
  125.       case FPE_INVALID        : type = "invalid";             break ;
  126.       case FPE_OVERFLOW       : type = "overflow";            break ;
  127.       case FPE_STACKOVERFLOW  : type = "stack overflow";      break ;
  128.       case FPE_STACKUNDERFLOW : type = "stack underflow";     break ;
  129.      }
  130.      sprintf(buf,"実数演算で異常が起きた(%s)",type) ;
  131.      prerr(150,buf) ;
  132. }
  133.  
  134. /******************************/
  135. /* usage() : 使用方法出力処理 */
  136. /******************************/
  137. static void usage(short type)
  138. {
  139.  title() ;
  140.  if(type==abnormal) fputs("\nI004: 起動パラメータが誤っている\n",stderr);
  141.  else  {                                /* pi のみで アーギュメントなしの時 */
  142.   fputs("\n  HAPPy is the H.Asano Pascal Processing system. (^_^)\n",
  143.              stderr);
  144.   fputs(
  145.    "\n  HAPPyはISO7185規格水準0にほぼ準拠したMS-DOS汎用Pascal処理系です。\n",
  146.             stderr) ;
  147.   fputs("  HAPPyの複写・再配付は自由です。\n", stderr) ;
  148.  }
  149.  
  150.  fputs("\n  piコマンドはpcコマンドで作ったP-codeオブジェクトを実行します。\n\n",stderr);
  151.  
  152.  fputs("  使い方:  pi [ オプション...] P-codeオブジェクトファイル名[.pco] [ オプション...]\n",
  153.        stderr) ;
  154.  fputs("  オプション:\n",stderr);
  155.  fputs("     -i ・・・ インタプリタ情報を出力する\n",stderr);
  156.  fputs("     -t ・・・ トレースをを標準出力に出力する\n",stderr);
  157.  fputs("     /f ・・・ プログラム引数のファイル名と実ファイル名を対応させる\n",
  158.         stderr);
  159.  fputs("                 例:  /fputfile=h:\\work\\list.txt\n",stderr) ;
  160.  
  161.  exit(2) ;
  162. }
  163.  
  164. /************************************/
  165. /* information() : -iオプション処理 */
  166. /************************************/
  167. static void information(void)
  168. {
  169.   short i,j     ;
  170.   short max = 0 ;
  171.  
  172.      title()  ;
  173.      fprintf(stderr,"\n * Program name = %s\n",progname) ;
  174.      fprintf(stderr," * Total memory = %5d words\n",Maxstore) ;
  175.      fprintf(stderr," * Object size  = %5d words\n",objsize)  ;
  176.      fprintf(stderr," * stack/heap   = %5d words\n",Maxstore-objsize) ;
  177.      if(fileno!=2) {
  178.       fputs(" * input,output以外のファイルと実ファイルの対応\n",stderr) ;
  179.       for(i=2;i<fileno;i++)
  180.        if(strlen(fi[i].filename) > max) max = strlen(fi[i].filename) ;
  181.       for(i=2;i<fileno;i++) {
  182.        fprintf(stderr,"    %s",fi[i].filename) ;
  183.        for(j=strlen(fi[i].filename);j<max;j++)
  184.         fputc(' ',stderr) ;             /* 最大の長さに合わせるため   */
  185.        fprintf(stderr," = %s\n",fi[i].rfname) ;
  186.       }
  187.      }
  188.      fputc('\n',stderr) ;
  189. }
  190.  
  191. /******************************************/
  192. /*  fileoption() : ファイルオプション処理 */
  193. /******************************************/
  194. static void fileoption(char *fileopt)
  195. {
  196.   short i=0 ;
  197.   short j   ;
  198.   short len ;
  199.   char logicalf[MaxIDlng+1] ;           /* プログラム上のファイル名   */
  200.  
  201.      if(fileno==2) usage(abnormal) ;    /* ファイル未使用時 /f は 指定不可*/
  202.  
  203.      while(*(fileopt+i)!='=') i++ ;     /* プログラム上のファイル名取得*/
  204.      if(i>MaxIDlng) i=MaxIDlng ;
  205.      for(j=0;j<i;j++)
  206.       logicalf[j] = (char)tolower(*(fileopt+j)) ;
  207.      logicalf[i] = '\0' ;
  208.  
  209.      j=2;
  210.      while((j<fileno) &&
  211.            strcmp(fi[j].filename,logicalf)) j++ ;
  212.      if(j==fileno) {                 /* プログラム上で使われていない時*/
  213.       title() ;
  214.       fprintf(stderr,"I005:/fオプション(%s)無効 : 無視する\n",fileopt) ;
  215.       return ;
  216.      }
  217.      if(fi[j].askflag) {                /* まだ/fオプションで未処理のファイル */
  218.       fi[j].askflag = false ;
  219.       fno++ ;                           /* /fオプション で 指定したファイル数 */
  220.      }
  221.      len = strlen(fileopt)-i-1 ;
  222.      if(len > MaxRFlen) len = MaxRFlen ;
  223.      strncpy(fi[j].rfname,fileopt+i+1,len) ;
  224.      fi[j].rfname[len] = '\0' ;
  225. }
  226.  
  227. /*****************************************/
  228. /*  inputfilename() : ファイル名入力処理 */
  229. /*****************************************/
  230. static void inputfilename(void)
  231. {
  232.   short i,j ;
  233.   short  ch ;
  234.  
  235.      title() ;
  236.      fputs("*HAPPy: ファイル( ",stderr) ;
  237.      for(i=2;i<fileno;i++)
  238.       if(fi[i].askflag)  fprintf(stderr,"%s ",fi[i].filename) ;
  239.      fputs(")の実ファイル名を入力して下さい\n",stderr);
  240.  
  241.      for(i=2;i<fileno;i++)
  242.       if(fi[i].askflag) {
  243.        fprintf(stderr," %s : ",fi[i].filename) ;
  244.        while(((ch=getc(stdin)) == ' ') || (ch == '\t'));
  245.                                         /* 空白,タブの読み飛ばし      */
  246.        j = 0 ;
  247.        while(ch != '\n') {
  248.         fi[i].rfname[j++] = (char)ch ;
  249.         if(j == MaxRFlen) break ;
  250.         ch = getc(stdin) ;
  251.        }  ;
  252.        fi[i].rfname[j] = '\0' ;
  253.       }
  254.      fputs("*HAPPy: ファイル名入力終了 *\n\n",stderr) ;
  255. }
  256.  
  257. /***************************************/
  258. /*   fcheck() : ファイルチェック処理    */
  259. /***************************************/
  260. static void fcheck(void)
  261. {
  262.      if(feof(pcofile))            /* 途中でファイルが終わってしまった*/
  263.       pierr("I002: P-codeオブジェクトファイル(%s)が不当である",pcofname) ;
  264. }
  265.  
  266. /***************************************/
  267. /*      init() :  初期設定処理         */
  268. /***************************************/
  269. static void init(void)
  270. {
  271.   short i   ;
  272.   char ch   ;
  273.   short headerlen     ;                 /* ヘッダ部分の長さ           */
  274.   char compversion[6] ;                 /* コンパイラバージョン番号   */
  275.  
  276.   /**** input,outputファイルのファイル情報を設定する ****/
  277.  
  278.      strcpy(fi[0].filename,"input")  ;
  279.      fi[0].fileadr  = inputadr       ;
  280.      fi[0].filesize = 1              ;
  281.      strcpy(fi[0].rfname,"標準入力") ;
  282.      fi[0].fp       = stdin          ;  /* 標準入力                   */
  283.      fi[0].mode     = inspection     ;  /* 検査モード                 */
  284.      fi[0].textfile = true           ;  /* テキストファイル           */
  285.  
  286.      strcpy(fi[1].filename,"output") ;
  287.      fi[1].fileadr  = outputadr      ;
  288.      fi[1].filesize = 1              ;
  289.      strcpy(fi[1].rfname,"標準出力") ;
  290.      fi[1].fp       = stdout         ;  /* 標準出力                   */
  291.      fi[1].mode     = generation     ;  /* 生成モード                 */
  292.      fi[1].textfile = true           ;  /* テキストファイル           */
  293.      fi[1].writelnflag = true        ;
  294.  
  295.      fileno = fno = 2 ;
  296.  
  297.      objsize = (short)filelength(fileno(pcofile));
  298.      i = 0 ;
  299.      do {                               /* バージョン番号を読む       */
  300.       ch = (char)fgetc(pcofile) ;
  301.       fcheck() ;
  302.      } while((compversion[i++]=ch)) ;
  303.      headerlen = i ;
  304.      if(strcmp(compversion,version))
  305.       pierr(
  306.        "I003: コンパイラ(Version %s)とバージョンが一致しない\n",compversion) ;
  307.      i = 0 ;
  308.      do {                               /* プログラム名を読む         */
  309.       progname[i] = (char)fgetc(pcofile) ;
  310.       fcheck() ;
  311.      } while(progname[i++]) ;
  312.      headerlen += i ;
  313.  
  314.      while((fi[fileno].fileadr = getw(pcofile)) != -1) {
  315.       fcheck() ;
  316.       headerlen += sizeof(short) ;
  317.       fi[fileno].filesize = getw(pcofile) ; /* バッファ変数の大きさ   */
  318.       headerlen += sizeof(short) ;
  319.       i = 0 ;
  320.       do {                               /* ファイル名を読む          */
  321.        fi[fileno].filename[i] = (char)fgetc(pcofile) ;
  322.        fcheck() ;
  323.       } while(fi[fileno].filename[i++]) ;
  324.       fi[fileno].mode = undefined  ;    /* ファイルモードは不定       */
  325.       fi[fileno].askflag  = true   ;    /* ファイル名問い合わせ要としておく*/
  326.       fi[fileno].textfile = false  ;    /* テキストでないとしておく   */
  327.  
  328.       headerlen += i ;
  329.       fileno++ ;
  330.      }
  331.      fcheck() ;
  332.  
  333.      headerlen += sizeof(short) ;
  334.      objsize   -= headerlen ;
  335.      fread((char*)store,objsize,1,pcofile) ; /* P-codeオブジェクトを読む*/
  336.      objsize /= sizeof(_store) ;
  337.  
  338.      for(i=0;i<fileno;i++) {
  339.       fi[i].fileadr += objsize ;        /* ファイルアドレスの修正     */
  340.       fi[i].filebuf =  store + fi[i].fileadr ; /* バッファ変数アドレス*/
  341.      }
  342. }
  343.  
  344. /******************************************/
  345. /*  main() : P-codeインタプリタメイン処理 */
  346. /******************************************/
  347. void main(int argc,char **argv)
  348. {
  349.   short i,j ;
  350.   boolean getfileflag = false ;
  351.  
  352.      wargc = argc ;
  353.      wargv = argv ;
  354.  
  355.      if(argc < 2)  usage(normal);       /* アーギュメントなしはusage  */
  356.  
  357.      while(--argc) {                    /* オプションの処理           */
  358.       if(**++argv == '-') {
  359.        for(i=1;*(*argv+i)!='\0';i++)
  360.         switch(*(*argv+i)) {
  361.          case 'I' :
  362.          case 'i' : infor = true   ;    /* information option         */
  363.                     break          ;
  364.          case 'T' :
  365.          case 't' : trace = true   ;    /* trace option               */
  366.                      break         ;
  367.          default  : usage(abnormal);    /* -t -i 以外はエラー         */
  368.         }
  369.        if(i==1)  usage(abnormal);       /* - だけの時はusage          */
  370.       }
  371.       else if(**argv == '/') {
  372.        if((*(*argv+1) == 'f') || (*(*argv+1) == 'F')) {
  373.         j=2 ;
  374.         while((*(*argv+j)) &&           /* /f・・・・=・・・・・ であること    */
  375.               (*(*argv+j)!='=')) j++ ;  /*    をチェックする          */
  376.         if((*(*argv+j)!='=') ||         /*   = がない                 */
  377.            !(*(*argv+j+1))   ||         /*   = で終わっている         */
  378.             (j==2))   usage(abnormal) ; /*   /f のみ                  */
  379.         fileoptflag = true ;            /* /fオプション あり              */
  380.        }
  381.       }
  382.       else {                            /* - / から始まらないアーギュメント */
  383.        if(getfileflag) {                /* すでにソースファイル名を   */
  384.          usage(abnormal);               /* 取得している時は 誤り      */
  385.          break ;                        /* whileループ脱出            */
  386.        }
  387.        getfileflag = true      ;        /* ファイル名取得済とする     */
  388.        *pcofname   = '\0'      ;
  389.        strcpy(pcofname, *argv) ;
  390.        j=0 ;                             /* 拡張子が省略されているか   */
  391.        while((*(pcofname+j)!='\0') && (*(pcofname+j)!='.')) j++ ;
  392.        if(*(pcofname+j)=='\0') strcat(pcofname,ext) ; /* 拡張子を付与  */
  393.       }
  394.      }
  395.  
  396.      if(getfileflag) {                  /* ファイル名が指定された時   */
  397.       pcofile = fopen(pcofname,"rb");
  398.       if(pcofile==NULL)
  399.        pierr("I001: P-codeオブジェクトファイル(%s)がない\n",pcofname);
  400.      }
  401.      else usage(abnormal) ;             /* ファイル名の指定がない時   */
  402.  
  403.      init()          ;                  /* 各種初期設定               */
  404.  
  405.      if(fileoptflag)                    /* /fオプションあり               */
  406.       while(--wargc)
  407.        if(**++wargv == '/')
  408.         if((*(*wargv+1) == 'f') || (*(*wargv+1) == 'F'))
  409.          fileoption(*wargv+2) ;
  410.  
  411.      if(fileno!=fno) inputfilename() ;  /* 全ファイルが決定していない時   */
  412.  
  413.      if(infor) information() ;          /* -i  インタプリタ情報出力        */
  414.  
  415.  
  416.      signal(SIGINT,cntl_c) ;            /* CTRL-Cシグナル登録         */
  417.      signal(SIGFPE,real_err) ;          /* 実数演算シグナル登録       */
  418.  
  419.      pc = 0          ;                  /* Program Counter 初期設定   */
  420.      mp = objsize    ;                  /* mp              初期設定   */
  421.      ep = mp + 5     ;                  /* ep              初期設定   */
  422.      np = Maxstore   ;                  /* np              初期設定   */
  423.      sp = store+mp-1 ;                  /* Stack Pointer   初期設定   */
  424.  
  425.      interpret() ;                      /* P-code命令解釈実行         */
  426. }
  427.